package SSU;

import SSU.Exceptions.*;
import java.util.Arrays;

/**
 * ArrayVector representsimple math
 * vector concept and store data in
 * array
 */
public class ArrayVector implements Vector {
    /**
     * Construct vector specified initial
     * size and with 0 values of elements
     *
     * @param   size    the size of vector
     *
     * @throws  NegativeSizeException
     *          if the specified size is negative
     */
    public ArrayVector(int size) {
        if (size < 0)
            throw new NegativeSizeException();
        elements = new double[size];
    }

    /**
     * Construct empty vector so it size is 0
     */
    public ArrayVector() {
        this(0);
    }

    /**
     * Constructs a vector containing the
     * elements of the specified array
     *
     * @param   array     array whose elements are
     *          to be placed into vector
     */
    public ArrayVector(double[] array) {
        elements = new double[array.length];
        System.arraycopy(array, 0, elements, 0, array.length);
    }

     /**
     * Returns a string representation of vector.  The string
     * representation consists of a list of elements enclosed
     * in square brackets "[]". Adjacent elements are separated
     * by the characters ", "(comma and space).
     *
     * @return  String representation of vector
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append('[').append(' ');
        for(int i = 0; i < size(); i++){
            sb.append(get(i)).append(' ');
        }
        sb.append(']');
        return sb.toString();
    }

    @Override
    public boolean equals(Object obj){
        if (!(obj instanceof ArrayVector))
            return false;
        ArrayVector vector = (ArrayVector)obj ;
        if (vector.size() != this.size())
            return false;
        for (int i=0; i < size(); i++){
            if (get(i) != vector.get(i))
                return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 97 * hash + Arrays.hashCode(this.elements);
        return hash;
    }

    /**
     * Returns the size of this vector.
     *
     * @return  the size of this vector
     */
    @Override
    public int size() {
        return elements.length;
    }

    /**
     * Returns the element at the specified position in this Vector.
     * 
     * @param   index   index of element to return
     * 
     * @return  element at specified position
     */
    @Override
    public double get(int index) {
        if (index < 0 || index >= size())
            throw new IndexException("Index: " + index);
        return elements[index];
    }

    /**
     * Set the element at the specified position in this Vector
     * with the specified element.
     *
     * @param   index   the index of the element to set
     * @param   value   new value of element
     */
    @Override
    public void set(int index, double value) {
        if (index < 0 || index >= size())
            throw new IndexException("Index: " + index);
        elements[index] = value;
    }

    /**
     * Sort vector using quick sort algorithm
     */
    public void sort(){
        quickSort(0, size()-1);
    }
    /**
     * Recursive implementation of quick sort
     *
     * @param   low     lower bound inclusive
     * @param   high    upper bound nclusive
     */
    private void quickSort(int low, int high) {
        int i = low, j = high;
        double pivot = get(low + (high-low)/2);
        while (i <= j) {
            while (get(i) < pivot) {
                i++;
            }
            while (get(j) > pivot) {
                j--;
            }
            if (i <= j) {
                swap(i, j);
                i++;
                j--;
            }
        }
        if (low < j)
            quickSort(low, j);
        if (i < high)
            quickSort(i, high);
    }

    public void swap(int i, int j) {
        double temp = get(i);
        set(i, get(j));
        set(j, temp);
    }
    /**
     * Container
     */
    private double[] elements;
}
